package com.swing.sky.system.framework.security.config;

import com.swing.sky.system.framework.security.handler.AuthenticationEntryPointImpl;
import com.swing.sky.system.framework.security.handler.LoginFailureHandler;
import com.swing.sky.system.framework.security.handler.LoginSuccessHandler;
import com.swing.sky.system.framework.security.handler.LogoutSuccessHandlerImpl;
import com.swing.sky.system.framework.security.service.UserDetailsServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.annotation.Resource;
import javax.sql.DataSource;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private UserDetailsServiceImpl userDetailsService;
    @Resource
    private LoginSuccessHandler loginSuccessHandler;
    @Resource
    private LoginFailureHandler loginFailureHandler;
    @Resource
    private AuthenticationEntryPointImpl authenticationEntryPoint;
    @Resource
    private DataSource systemDataSource;
    @Resource
    private LogoutSuccessHandlerImpl logoutSuccessHandler;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //\u7981\u7528csrf \uFF08\u8DE8\u7AD9\u8BF7\u6C42\u4F2A\u9020\uFF09
                .csrf().disable()
                .headers().frameOptions().disable()
                .and()
                // \u8FC7\u6EE4\u8BF7\u6C42
                .authorizeRequests()
                // \u5BF9\u4E8E\u767B\u5F55login \u9A8C\u8BC1\u7801captchaImage \u5141\u8BB8\u533F\u540D\u8BBF\u95EE
                .antMatchers("/login", "/captcha").permitAll()
                //\u9759\u6001\u8D44\u6E90\u7684\u8BBF\u95EE\u65E0\u9700\u8BA4\u8BC1
                .antMatchers(
                        HttpMethod.GET,
                        "/*.html",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/**/*.jpg",
                        "/**/*.png",
                        "/**/*.ico",
                        "/**/*.map",
                        "/**/*.woff",
                        "/**/*.woff2",
                        "/**/*.ttf"
                ).permitAll()
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/*/api-docs").permitAll()
                // \u9664\u4E0A\u9762\u5916\u7684\u6240\u6709\u8BF7\u6C42\u5168\u90E8\u9700\u8981\u9274\u6743\u8BA4\u8BC1
                .anyRequest().authenticated()
                .and()
                //\u8BA4\u8BC1\u5931\u8D25\u5904\u7406\u7C7B
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
                .and()
                //\u767B\u51FA\u6210\u529F\u5904\u7406\u7C7B\uFF08\u5982\u679C\u6709\u8BB0\u4F4F\u6211\u7684\u529F\u80FD\uFF0C\u8FD9\u91CC\u4F1A\u81EA\u52A8\u5220\u9664cookie\u4E2D\u7684remember-me
                .logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler)
                .and()
                //\u914D\u7F6E\u8868\u5355\u767B\u5F55
                .formLogin()
                //\u6307\u5B9A\u767B\u5F55\u9875\u9762
                .loginPage("/login")
                //\u6307\u5B9A\u767B\u5F55\u5904\u7406\u7A0B\u5E8F
                .loginProcessingUrl("/login")
                //\u6307\u5B9A\u767B\u5F55\u6210\u529F\u5904\u7406\u7C7B
                .successHandler(loginSuccessHandler)
                //\u6307\u5B9A\u767B\u5F55\u5931\u8D25\u5904\u7406\u7C7B
                .failureHandler(loginFailureHandler)
                //\u5982\u679C\u662F\u7531\u540E\u7AEF\u63A7\u5236\u91CD\u5B9A\u5411\uFF08\u672C\u9879\u76EE\u662F\u7531\u524D\u7AEF\u6839\u636EJSON\u7ED3\u679C\u6765\u91CD\u5B9A\u5411,\u56E0\u6B64\u8FD9\u91CC\u4E0D\u4F7F\u7528\uFF09
//                .defaultSuccessUrl("/index")
//                .failureUrl("/login")
                .and()
                //\u8BB0\u4F4F\u6211\u7684\u914D\u7F6E
                .rememberMe()
                //\u4E00\u76F4\u5F00\u542F\u8BB0\u4F4F\u6211\u7684\u529F\u80FD
                .alwaysRemember(true)
                .rememberMeCookieName("sky-remember-me")
                //\u914D\u7F6E\u4EE4\u724C\u7684\u5B58\u50A8\u65B9\u5F0F\uFF08\u5B58\u50A8\u5728\u6570\u636E\u5E93\u4E2D\uFF09
                .tokenRepository(persistentTokenRepository())
                //\u8BB0\u4F4F\u6211\u7684\u6709\u6548\u671F
                .tokenValiditySeconds(60 * 60 * 24)
                .userDetailsService(userDetailsService);
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(systemDataSource);
        return jdbcTokenRepository;
    }
}